<template>
  <div class="canvas-wrap" ref="canvasWrapRef">
    <v-stage
      ref="stage"
      class="stage"
      :x="stageConfig.x"
      :y="stageConfig.y"
      :config="{
        width: stageConfig.width,
        height: stageConfig.height,
      }"
      :offsetX="stageConfig.offsetX"
      :offsetY="stageConfig.offsetY"
      :scaleX="stageConfig.scaleX"
      :scaleY="stageConfig.scaleX"
      :draggable="stageConfig.draggable"
      @mousemove="handleMouseMove"
      @dragstart="handleDragstart"
      @dragmove="handleDragmove"
      @wheel="handleWheel"
    >
      <v-layer>
        <v-image :config="imageConfig" :image="imageDom" ref="image" class="image"></v-image>
        <v-rect
          class="rect"
          v-for="(item, index) in rectList"
          :key="index"
          :config="{
            x: item.x,
            y: item.y,
            width: item.width,
            height: item.height,
            fill: 'rgba(0,0,0,0.1)',
          }"
          :draggable="false"
        />
        <coordinateAxis
          :width="stageConfig.width"
          :height="stageConfig.height"
          :key="stageConfig.width + stageConfig.height"
        />
      </v-layer>
    </v-stage>
  </div>
</template>

<script>
import coordinateAxis from './coordinateAxis.vue'
export default {
  name: 'prev-img',
  components: {
    coordinateAxis,
  },
  props: {
    draggable: {
      type: Boolean,
      default: true,
    },
    imageSrc: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      stageConfig: {
        x: 0,
        y: 0,
        width: 500,
        height: 500,
        scaleX: 1,
        scaleY: 1,
        offsetX: 0,
        offsetY: 0,
        draggable: true,
      },
      imageConfig: {
        x: 0,
        y: 0,
        width: 0,
        height: 0,
        offsetX: 0,
        offsetY: 0,
        scaleX: 1,
        scaleY: 1,
        rotation: 0,
        draggable: false,
      },
      imageDom: new Image(),
      initImageScale: 1,
      rectList: [],
    }
  },
  created() {
    this.imageDom.src = this.imageSrc
    this.imageDom.onload = () => {
      // 设置画布大小
      const { width, height } = this.$refs.canvasWrapRef.getBoundingClientRect()
      this.stageConfig.x = width / 2
      this.stageConfig.y = height / 2
      this.stageConfig.width = width
      this.stageConfig.height = height
      this.stageConfig.offsetX = width / 2
      this.stageConfig.offsetY = height / 2
      // 设置图片大小
      const {
        width: imageWidth,
        height: imageHeight,
        scale,
      } = initImageSize(this.imageDom, this.stageConfig)
      // 记录图片缩放比例
      this.initImageScale = scale
      this.imageConfig.x = this.stageConfig.x
      this.imageConfig.y = this.stageConfig.y
      this.imageConfig.width = imageWidth
      this.imageConfig.height = imageHeight
      this.imageConfig.offsetX = imageWidth / 2
      this.imageConfig.offsetY = imageHeight / 2
    }
    // 注册键盘事件
    window.addEventListener('keydown', this.handleKeydown)
  },
  methods: {
    zoom(scale) {
      const res = this.stageConfig.scaleX * (1 + scale)
      console.log(res, 'res')
      if (res < 0.1 || res > 10) return
      this.stageConfig.scaleX = res
      this.stageConfig.scaleY = res
    },
    rotate(angle) {
      this.imageConfig.rotation += angle
    },
    handleWheel(event) {
      const { deltaY } = event.evt
      const scale = -deltaY / 1000
      this.zoom(scale)
    },
    handleDragmove(event) {
      const { x, y } = event.target.attrs
      this.stageConfig.x = x
      this.stageConfig.y = y
    },
    handleClick(event) {
      const targetClass = event.target.attrs.class
      console.log('点击元素类名', targetClass)
    },
    // 根据鼠标位置决定下一步需要做什么
    handleMouseMove(event) {
      const targetClass = event.target.attrs.class
      switch (targetClass) {
        case 'stage':
          console.log('stage')
          break;
        case 'image':
          console.log('image')
          break;
        case 'rect':
          console.log('rect')
          break;
        default:
          console.log('没有目标')
      }
    },
    handleDragstart(event) {
      const { x, y } = mousePosToStagePos(event.evt, this.stageConfig)
      this.rectList.push({
        x,
        y,
        width: 100,
        height: 100,
      })
    },
    // 通过键盘控制画布移动
    handleKeydown(event) {
      const { keyCode } = event
      const { x, y } = this.stageConfig
      switch (keyCode) {
        case 37:
          this.stageConfig.x = x - 10
          break
        case 38:
          this.stageConfig.y = y - 10
          break
        case 39:
          this.stageConfig.x = x + 10
          break
        case 40:
          this.stageConfig.y = y + 10
          break
      }
    },
  },
}

/**
 * 鼠标位置转为画布坐标
 */
function mousePosToStagePos(mouse, stageConfig) {
  // 画布距离左侧和顶部的距离
  const { x, y, offsetX, offsetY, scaleX, scaleY } = stageConfig
  const left = x - offsetX * scaleX
  const top = y - offsetY * scaleY
  // 鼠标位置
  const { offsetX: mouseX, offsetY: mouseY } = mouse
  const realX = mouseX - left
  const realY = mouseY - top
  return {
    x: realX / scaleX,
    y: realY / scaleY,
  }
}

/**
 * 初始化图片大小
 * @param {Object} imageDom 图片宽高
 * @param {Object} stageConfig 画布宽高
 */
function initImageSize(imageDom, stageConfig) {
  const { width, height } = imageDom
  console.log('原图大小', width, height)
  const { width: stageWidth, height: stageHeight } = stageConfig
  const scaleX = stageWidth / width
  const scaleY = stageHeight / height
  const scale = Math.min(scaleX, scaleY)
  return {
    width: width * scale,
    height: height * scale,
    scale,
  }
}
</script>

<style scoped lang="scss">
.canvas-wrap {
  border: 1px solid#ccc;
}
</style>
